#if defined (__cplusplus) || defined (c_plusplus)
#include <c_varieties.h>
#ifdef __EXTERN_C__
	EXTERN_FC ( extern int yylex, ());
#else
	extern int yylex();
#endif
	extern void yyerror(char *);
	extern int yyparse();
#endif
#ifdef __cplusplus
EXTERN_FC ( extern int printf,    (const char*, DOTDOTDOT) );
EXTERN_FC ( extern void *memcpy,  (void *, const void *, int) );
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "els_vm.h"
#include "els_vm_bytecode.h"
#include "hash.h"
#include "inout.h"
#include "els_vm_tree.h"
#include "unit.h"
#include "els.h"
#include "func.h"

int yyparse (void);
#define malloc els_vm_malloc
#define realloc els_vm_realloc
#define free els_vm_free

#ifndef LISTING
#define LISTING 0
#endif
#ifndef CODE_BLOCK
#define CODE_BLOCK 256
#endif
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif

# define YYERRCODE 256

#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
# define YYNPROD 100
# define YYLAST 311

int   maxcode;
int   maxmain;
Long   maxcurr; 
Byte  *funcCode = NULL;
Byte **initcode;
Byte  *basepc;
int   maincode;
int   pc;


#define MAXVAR 32
#define MAXLETS 32
#define MAXFIELDS FIELDS_PER_FLUSH*2

Long varbuffer[MAXVAR]; 
int  nvarbuffer=0;	
Word localvar[MAXLETS];  
int  nlocalvar=0;	     
Word fields[MAXFIELDS]; 
int  nfields=0;

void yyerror (char *s){
 	char msg[256];
 	sprintf (msg,"%s \t%s\t  \n在文件 \"%s\" 中第 %d 行", s,els_lasttext (), els_parsedfile,els_linenumber );
 	els_error (msg);
}

void code_byte (Byte c){
 	if (pc>maxcurr-2){
  		if (maxcurr >= MAX_INT) els_error("代码内存溢出");
  		maxcurr *= 2;
  		if (maxcurr >= MAX_INT) maxcurr = MAX_INT;
  		basepc = growvector(basepc, maxcurr, Byte);
 	}
 	basepc[pc++] = c;
}

void code_word (Word n){
 	CodeWord code;
 	code.w = n;
 	code_byte(code.m.c1);
 	code_byte(code.m.c2);
}

void code_float (float n){
	CodeFloat code;
 	code.f = n;
 	code_byte(code.m.c1);
 	code_byte(code.m.c2);
 	code_byte(code.m.c3);
 	code_byte(code.m.c4);
}

void code_code (ELS_FUNC *tf){
 	CodeCode code;
 	code.tf = tf;
 	code_byte(code.m.c1);
 	code_byte(code.m.c2);
 	code_byte(code.m.c3);
 	code_byte(code.m.c4);
}

void code_word_at (Byte *p, Word n){
 	CodeWord code;
 	code.w = n;
 	*p++ = code.m.c1;
 	*p++ = code.m.c2;
}

void push_field (Word name){
  	if (nfields < MAXFIELDS) fields[nfields++] = name;
  	else els_error ("嵌套构造函数中的字段过多");
}

void flush_record (int n){
  	int i;
  	if (n == 0) return;
	code_byte(STORERECORD);
  	code_byte(n);
  	for (i=0; i<n; i++) code_word(fields[--nfields]);
}

void flush_list (int m, int n){
  	if (n == 0) return;
  	if (m == 0) code_byte(STORELIST0); 
  	else if (m < 255){
    	code_byte(STORELIST);
    	code_byte(m);
  	}else els_error ("链表构造函数所占空间过长");
  	code_byte(n);
}

void add_localvar (Word name){
 	if (nlocalvar < MAXLETS) localvar[nlocalvar++] = name;
 	else els_error ("局部变量过多");
}

void store_localvar (Word name, int n){
 	if (nlocalvar+n < MAXLETS) localvar[nlocalvar+n] = name;
 	else els_error ("局部变量过多");
}

void add_varbuffer (Long var){
 	if (nvarbuffer < MAXVAR) varbuffer[nvarbuffer++] = var;
 	else els_error ("可变缓冲区溢出");
}

void code_number (float f){ 
  	Word i = (Word)f;
  	if (f == (float)i){
   		if (i <= 2) code_byte(PUSHNUM0 + i);
   		else if (i <= 255){
    		code_byte(PUSHBYTE);
    		code_byte(i);
   		}else{
    		code_byte(PUSHWORD);
    		code_word(i);
   		}
	}else{
   		code_byte(PUSHFLOAT);
   		code_float(f);
  	}
}

int els_localname (Word n){
 	int i;
 	for (i=nlocalvar-1; i >= 0; i--) if (n == localvar[i]) return i;	
 	return -1;		        
}

void els_pushvar (Long number){ 
 	if (number > 0){
  		code_byte(PUSHGLOBAL);
  		code_word(number-1);
 	}else if (number < 0){
  		number = (-number) - 1;
  		if (number < 10) code_byte(PUSHLET0 + number);
  		else{
   			code_byte(PUSHLET);
   			code_byte(number);
  		}
 	}else{
  		code_byte(PUSHINDEXED);
 	}
}

void els_codecompare (int n){
 	if (n+nlocalvar == 0) code_byte(ADJUST0);
 	else{
   		code_byte(ADJUST);
   		code_byte(n+nlocalvar);
 	}
}

void change2main (void){
  	pc=maincode; basepc=*initcode; maxcurr=maxmain;
  	nlocalvar=0;
}

void savemain (void){
  	maincode=pc; 
	*initcode=basepc; 
	maxmain=maxcurr;
}

void init_func (void){
  	if (funcCode == NULL)	{
   		funcCode = newvector(CODE_BLOCK, Byte);
   		maxcode = CODE_BLOCK;
  	}
  	savemain();
  	pc=0; basepc=funcCode; maxcurr=maxcode; 
  	nlocalvar = 0;
  	els_vm_codedebugline(els_linenumber);
}

void codereturn (void){
  	if (nlocalvar == 0) code_byte(RETCODE0);
  	else{
    	code_byte(RETCODE);
    	code_byte(nlocalvar);
  	}
}

void els_vm_codedebugline (int line){
  	int lastline = 0;
  	if (els_debug && line != lastline){
    	code_byte(SETLINE);
    	code_word(line);
    	lastline = line;
  	}
}

int compare_functioncall (Long exp, int i){
	if (exp <= 0) return -exp;
  	else{
    	int temp = basepc[exp];
    	basepc[exp] = i;
    	return temp+i;
  	}
}

void compare_mult_assign (int vars, Long exps, int temps){
  	if (exps > 0){ 
		int diff = vars - basepc[exps];
	    if (diff >= 0) compare_functioncall(exps, diff);
    	else{
      		compare_functioncall(exps, 0);
      		els_codecompare(temps);
    	}
  	}
  	else if (vars != -exps)
    els_codecompare(temps);
}

void storesinglevar (Long v){
 	if (v > 0){
   		code_byte(STOREGLOBAL);
   		code_word(v-1);
 	}else if (v < 0){
   		int number = (-v) - 1;
   		if (number < 10) code_byte(STORELET0 + number);
   		else{
     		code_byte(STORELET);
     		code_byte(number);
   		}
 	}
 	else code_byte(STOREINDEXED0);
}

void els_codestore (int i){
 	if (varbuffer[i] != 0) storesinglevar(varbuffer[i]);
 	else{
  		int j;
  		int upper=0;   
  		int param;		
  		for (j=i+1; j <nvarbuffer; j++) if (varbuffer[j] == 0) upper++;
  		param = upper*2 + i;
  		if (param == 0) code_byte(STOREINDEXED0);
  		else{
   			code_byte(STOREINDEXED);
   			code_byte(param);
  		}
 	}
}

void codeIf (Long thenAdd, Long elseAdd){
  	Long elseinit = elseAdd+sizeof(Word)+1;
  	if (pc == elseinit){
    	pc -= sizeof(Word)+1;
    	elseinit = pc;
  	}else{
    	basepc[elseAdd] = JMP;
    	code_word_at(basepc+elseAdd+1, pc-elseinit);
  	}
  	basepc[thenAdd] = IFFJMP;
  	code_word_at(basepc+thenAdd+1,elseinit-(thenAdd+sizeof(Word)+1));
}

void els_parse (ELS_FUNC *tf){
 	els_debug = 0;
 	initcode = &(tf->code);
 	*initcode = newvector(CODE_BLOCK, Byte);
 	maincode = 0; 
 	maxmain = CODE_BLOCK;
 	change2main();
 	if (yyparse ()) els_error("语法错误");
 	savemain();
 	(*initcode)[maincode++] = RETCODE0;
 	tf->size = maincode;
}



typedef union  
{
 	int   vInt;
 	float vFloat;
 	char *pChar;
 	Word  vWord;
 	Long  vLong;
 	ELS_FUNC *pFunc;
 	Els_Type_Tree *pNode;
} YYSTYPE;
YYSTYPE yylval, yyval;
extern int yychar;
extern int yyerrflag;


int const yyexca[] ={
	-1, 1,0, -1,-2, 0,-1, 14,
	61, 88,44, 88,-2, 94,-1, 22,
	40, 7,-2, 94,-1, 29,40, 59,
	123, 59,-2, 46,-1, 44,123, 56,
	-2, 63,-1, 71,123, 56,-2, 84,
	-1, 76,275, 30,276, 30,277, 30,
	278, 30,62, 30,60, 30,279, 30,
	280, 30,281, 30,43, 30,45, 30,
	42, 30,47, 30,94, 30,-2, 65,
	-1, 77,91, 94,46, 94,-2, 89,
	-1, 132,123, 56,-2, 78,-1, 138,
	123, 56,-2, 63,-1, 155,275, 30,
	276, 30,277, 30,278, 30,62, 30,
	60, 30,279, 30,280, 30,281, 30,
	43, 30,45, 30,42, 30,47, 30,
	94, 30,-2, 67,
};

const int const yyact[311]={

    61,    59,   148,    60,   141,    62,   118,    61,    59,    90,
    60,    89,    62,    86,    84,    18,    42,   168,    54,   164,
    55,    61,    59,   156,    60,    54,    62,    55,    61,    59,
   115,    60,    73,    62,   157,    61,    59,    19,    60,    54,
    62,    55,    61,    59,    82,    60,    54,    62,    55,   158,
   159,   129,    63,    54,    91,    55,   111,    25,   121,    63,
    54,   109,    55,   127,    26,    61,    59,    26,    60,    27,
    62,     7,    27,    63,    71,     8,    33,     9,    11,    63,
    63,    12,     6,    80,    67,    18,    13,    63,    68,     7,
    48,    40,     4,     8,    63,     9,    24,    76,   138,    12,
    81,   133,    76,    18,    61,    59,    61,    60,    39,    62,
    20,    62,   146,   130,   117,   132,    69,    63,   123,    48,
   104,   105,   122,    70,   124,   120,    72,   106,    48,    50,
    29,    46,    17,    44,   128,    47,    85,    23,    83,    76,
    51,    28,    92,    93,    94,    95,    96,    97,    98,    99,
   100,   101,   102,   103,    88,   140,    63,    45,    63,    36,
   112,    14,   131,   139,    47,    35,    22,   151,   126,   134,
   125,    78,   137,    47,   153,    74,    38,    37,    75,   142,
   116,     5,     3,   154,     2,    49,    21,   147,    16,    87,
   152,   165,   163,    11,   110,   108,    76,   155,   145,   160,
    77,    79,    41,   171,   135,   107,   162,   173,   161,   136,
    15,    43,    10,   167,   143,   144,     1,     0,   169,     0,
   119,   149,   150,     0,   170,     0,   172,     0,     0,     0,
     0,     0,     0,    65,    66,    53,    56,    57,    58,    64,
    65,    66,    53,    56,    57,    58,    64,    17,   166,     0,
   114,     0,     0,    52,    65,    66,    53,    56,    57,    58,
    64,    65,    66,    53,    56,    57,    58,    64,    65,    66,
    53,    56,    57,    58,    64,     0,    14,    53,    56,    57,
    58,    64,    32,     0,     0,    32,     0,     0,     0,     0,
     0,     0,     0,     0,     0,    30,    31,    18,    30,    31,
   113,     0,     0,     0,    64,     0,     0,    34,     0,     0,
    34 };
const int const yypact[174]={

 -1000,  -188, -1000, -1000,    51, -1000,  -258,    24, -1000, -1000,
    47, -1000,  -257, -1000, -1000,    93, -1000,    73, -1000, -1000,
 -1000,    89, -1000,    82,    -7, -1000,    24,    24, -1000,    73,
 -1000, -1000, -1000, -1000,    24,   -49, -1000,    24, -1000,    24,
  -258,    39, -1000, -1000,    24, -1000,  -259,    24,  -260, -1000,
  -262,  -264, -1000,    24,    24,    24,    24,    24,    24,    24,
    24,    24,    24,    24,    24, -1000, -1000,    86,   -21,   -15,
   -15,    27,   -14,  -236, -1000,    70, -1000, -1000,    44, -1000,
  -267,    24,    84,    70, -1000,   -35, -1000,    81,    74, -1000,
 -1000, -1000,    23,    23,    23,    23,    23,    23,    64,    64,
   -15,   -15,   -15,    62, -1000, -1000, -1000,   -62, -1000,    69,
    71, -1000,   -21,    40, -1000,    24,  -170, -1000, -1000,    70,
 -1000, -1000, -1000,  -269, -1000,    24,    24, -1000,    53, -1000,
  -271, -1000,    24,    24, -1000,   -21,    51, -1000,    24,    24,
  -244, -1000,  -212,     0,     0, -1000,  -271, -1000,    40,   -21,
   -21, -1000, -1000, -1000,    51, -1000, -1000,  -248, -1000,    24,
 -1000,    69,  -250, -1000, -1000, -1000,   -42, -1000, -1000, -1000,
 -1000, -1000,  -212, -1000 };
const int const yypgo[46]={

     0,   216,    54,    44,   138,    76,    57,   212,   211,   210,
   205,   202,   201,   199,    61,   198,   195,   194,   189,   159,
   188,   186,   185,   184,   182,    92,    37,   181,   130,    32,
   180,    88,    34,   177,   176,   175,   172,   141,   170,   168,
   165,   163,   154,   134,    51,    56 };
const int const yyr1[100]={

     0,     1,     1,     1,    23,    23,    24,    21,    21,    22,
    30,    30,    26,    26,    25,    33,    25,    34,    25,    25,
    25,    25,    32,    32,    32,    35,    29,    36,    36,     2,
    31,     6,     6,     6,     6,     6,     6,     6,     6,     6,
     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,
     6,     6,    38,     6,    39,     6,    40,    37,     5,     9,
     9,     8,     8,     3,     3,     4,    41,     4,    18,    18,
    42,    42,    43,    10,    10,    15,    15,    44,    44,    13,
    13,    14,    14,    45,    16,    16,    17,    17,     7,     7,
    19,    19,    19,    20,    28,    11,    11,    12,    12,    27 };
const int const yyr2[100]={

     0,     0,     4,     4,     4,     2,     7,     3,     7,    11,
     0,     6,     0,     2,    17,     1,    17,     1,    13,     7,
     2,     7,     0,     4,    15,     1,     7,     0,     7,     1,
     3,     7,     7,     7,     7,     7,     7,     7,     7,     7,
     7,     7,     7,     7,     5,     3,     3,     3,     3,     3,
     3,     5,     1,    11,     1,    11,     1,     9,     5,     3,
     7,     7,     3,     1,     3,     3,     1,     9,     1,     3,
     3,     7,     1,     7,     5,     1,     5,     0,     2,     1,
     5,     3,     7,     7,     1,     5,     3,     7,     3,     7,
     3,     9,     7,     3,     3,     3,     7,     1,     5,     3 };
const int const yychk[174]={

 -1000,    -1,   -23,   -24,   -25,   -27,   270,   259,   263,   265,
    -7,    -5,   269,   274,   -19,    -9,   -20,   -28,   273,   -26,
    59,   -21,   -19,   -28,   -31,    -6,    40,    45,   -37,   -28,
   271,   272,   258,    -5,   283,   -40,   -19,   -33,   -34,    61,
    44,   -11,   273,    -8,    40,   -37,    58,    91,    46,   -22,
    40,    58,   260,   277,    60,    62,   278,   279,   280,    43,
    45,    42,    47,    94,   281,   275,   276,    -6,   -31,   -31,
   -31,   123,   -31,   -29,   -35,    -4,    -6,   -19,   -28,   -12,
    44,    61,    -3,    -4,   273,   -31,   273,   -18,   -42,   273,
   273,    -2,   -31,   -31,   -31,   -31,   -31,   -31,   -31,   -31,
   -31,   -31,   -31,   -31,    -2,    -2,    41,   -10,   -16,   -14,
   -17,   -45,   -31,   273,   264,   266,   -30,    44,   273,    -4,
    41,    93,    41,    44,   -29,   -38,   -39,   125,   -43,   -44,
    44,   -44,    44,    61,    -2,   -31,   -25,   -36,   268,   -41,
   -29,   273,    -2,   -31,   -31,   -15,    59,   -45,   273,   -31,
   -31,   -29,    -2,   -26,    -3,    -6,   267,   -32,   261,   262,
   -13,   -14,    -2,   -26,   267,   -29,   -31,   -44,   267,   260,
    -2,   -29,    -2,   -32 };
const int const yydef[174]={

     1,    -2,     2,     3,    12,     5,     0,    56,    15,    17,
     0,    20,     0,    99,    -2,    56,    90,    59,    93,     4,
    13,     0,    -2,     0,     0,    30,    56,    56,    45,    -2,
    47,    48,    49,    50,    56,     0,    94,    56,    25,    56,
     0,    97,    95,    58,    -2,    62,     0,    56,     0,     6,
    68,     0,    29,    56,    56,    56,    56,    56,    56,    56,
    56,    56,    56,    56,    56,    29,    29,    30,     0,    44,
    51,    -2,     0,     0,    10,    19,    -2,    -2,     0,    21,
     0,    56,     0,    64,    60,     0,    92,     0,    69,    70,
     8,    25,    32,    33,    34,    35,    36,    37,    38,    39,
    40,    41,    42,    43,    52,    54,    31,     0,    72,    77,
    77,    81,    86,    93,    29,    56,    27,    66,    96,    98,
    61,    91,    25,     0,    29,    56,    56,    57,    75,    74,
    78,    85,    -2,    56,    25,    29,    12,    26,    -2,    56,
     0,    71,    22,    53,    55,    73,    79,    82,     0,    87,
    83,    29,    18,    11,    12,    -2,     9,     0,    25,    56,
    76,    77,     0,    28,    14,    23,     0,    80,    16,    29,
    25,    29,    22,    24 };
typedef struct { char *t_name; int t_val; } yytoktype;



#define YYERROR		goto yyerrlab
#define YYACCEPT	return(0)
#define YYABORT		return(1)
#define YYBACKUP( newtoken, newvalue )\
{\
	if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
	{\
		yyerror( "未定义的语法错误" );\
		goto yyerrlab;\
	}\
	yychar = newtoken;\
	yystate = *yyps;\
	yylval = newvalue;\
	goto yynewstate;\
}
#define YYRECOVERING()	(!!yyerrflag)
#define YYCOPY(to, from, type) \
	(type *) memcpy(to, (char *) from, yynewmax * sizeof(type))






int yydebug;		

#define YYFLAG	(-1000)


YYSTYPE yy_yyv[YYMAXDEPTH], *yyv = yy_yyv;	
int yy_yys[YYMAXDEPTH], *yys = yy_yys;	

YYSTYPE *yypv;			
int *yyps;		

int yystate;			
int yytmp;			

#if defined(__cplusplus) || defined(__STDC__) || defined(lint)
int __yaccpar_lint_hack__ = 0;   
#endif

int yynerrs;			

int yyerrflag;		
int yychar;			
unsigned yymaxdepth = YYMAXDEPTH;

int yyparse(){
    register YYSTYPE *yypvt = (YYSTYPE*)0 ;       
	yypv = &yyv[-1];
	yyps = &yys[-1];
	yystate = 0;
	yytmp = 0;
	yynerrs = 0;
	yyerrflag = 0;
	yychar = -1;
	
	register YYSTYPE *yy_pv;	
	register int *yy_ps;		
	register int yy_state;		
	register int  yy_n;		

	goto yystack;
	yynewstate:
		yy_pv = yypv;
		yy_ps = yyps;
		yy_state = yystate;
		goto yy_newstate;

	yystack:
		yy_pv = yypv;
		yy_ps = yyps;
		yy_state = yystate;

	yy_stack:

		if ( ++yy_ps >= &yys[ yymaxdepth ] ){
            int yyps_index = (yy_ps - yys);
            int yypv_index = (yy_pv - yyv);
            int yypvt_index = (yypvt - yyv);
            int yynewmax;
			yynewmax = yymaxdepth + YYMAXDEPTH;
			if (yymaxdepth == YYMAXDEPTH){
				YYSTYPE *newyyv = (YYSTYPE*)malloc(yynewmax*sizeof(YYSTYPE));
				int *newyys = (int*)malloc(yynewmax*sizeof(int));
				if (newyys != 0 && newyyv != 0){
					yys = YYCOPY(newyys, yys, int);
					yyv = YYCOPY(newyyv, yyv, YYSTYPE);
				}
				else yynewmax = 0;	
			}else{
				yyv = (YYSTYPE*)realloc((char*)yyv,yynewmax * sizeof(YYSTYPE));
				yys = (int*)realloc((char*)yys,yynewmax * sizeof(int));
				if (yys == 0 || yyv == 0) yynewmax = 0;	
			}
			if (yynewmax <= yymaxdepth)	{
				yyerror( "yacc stack overflow" );
				YYABORT;
			}
			yymaxdepth = yynewmax;
            yy_ps = yys + yyps_index;
            yy_pv = yyv + yypv_index;
            yypvt = yyv + yypvt_index;
		}
		*yy_ps = yy_state;
		*++yy_pv = yyval;

	yy_newstate:
		if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG ) goto yydefault;	
		if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) ) yychar = 0;	
		if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) ) goto yydefault;
		if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar ){
			yychar = -1;
			yyval = yylval;
			yy_state = yy_n;
			if ( yyerrflag > 0 ) yyerrflag--;
			goto yy_stack;
		}

	yydefault:
		if ( ( yy_n = yydef[ yy_state ] ) == -2 ){
			if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) ) yychar = 0;		
			volatile register int *yyxi = (int*)yyexca;
			while ( ( *yyxi != -1 ) ||( yyxi[1] != yy_state ) ){
					yyxi += 2;
			}
			while ( ( *(yyxi += 2) >= 0 ) &&( *yyxi != yychar ) );
			if ( ( yy_n = yyxi[1] ) < 0 ) YYACCEPT; 
			
		}
		if ( yy_n == 0 ){
			switch ( yyerrflag ){
				case 0:		/* new error */
					yyerror( "语法错误" );
					goto skip_init;
					yyerrlab:
						yy_pv = yypv;
						yy_ps = yyps;
						yy_state = yystate;
						yynerrs++;
				skip_init:
				case 1:
				case 2: yyerrflag = 3;
				while ( yy_ps >= yys ){
					yy_n = yypact[ *yy_ps ] + YYERRCODE;
					if ( yy_n >= 0 && yy_n < YYLAST &&yychk[yyact[yy_n]] == YYERRCODE){
						yy_state = yyact[ yy_n ];
						goto yy_stack;
					}
					yy_ps--;
					yy_pv--;
				}
				YYABORT;
				case 3:		
					if ( yychar == 0 )	YYABORT;
					yychar = -1;
					goto yy_newstate;
				}
		}
		
		yytmp = yy_n;		
        yypvt = yy_pv;   
		             
		volatile register int yy_len = yyr2[ yy_n ];
		
		if ( !( yy_len & 01 ) ){
			yy_len >>= 1;
			yyval = ( yy_pv -= yy_len )[1];	/* $$ = $1 */
			yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] + *( yy_ps -= yy_len ) + 1;
			if ( yy_state >= YYLAST ||yychk[ yy_state =yyact[ yy_state ] ] != -yy_n ){
					yy_state = yyact[ yypgo[ yy_n ] ];
			}
			goto yy_stack;
		}
		
		yy_len >>= 1;
		yyval = ( yy_pv -= yy_len )[1];	/* $$ = $1 */
		yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] + *( yy_ps -= yy_len ) + 1;
		if ( yy_state >= YYLAST ||yychk[ yy_state = yyact[ yy_state ] ] != -yy_n ){
			yy_state = yyact[ yypgo[ yy_n ] ]; 
		}
		yystate = yy_state;
		yyps = yy_ps;
		yypv = yy_pv;
		
		switch( yytmp ){		
			
			case 6:{ 
				code_byte(PUSHFC);
				code_code(yypvt[-0].pFunc);
				storesinglevar(yypvt[-1].vLong);
	       	} 
				break;
			case 7:{
				yyval.vLong =yypvt[-0].vLong; init_func(); 
			}
				break;
			case 8:{
	  			code_byte(PUSHSTRING);
	  			code_word(els_vm_findconstant(yypvt[-0].pNode));
	  			yyval.vLong = 0;  /* indexed variable */
	  			init_func();
	  			add_localvar(els_vm_findsymbolbyname("this"));
			} 
				break;
			case 9:{
          		codereturn();
	  			yyval.pFunc = new(ELS_FUNC);
	  			yyval.pFunc->size = pc;
	  			yyval.pFunc->code = newvector(pc, Byte);
	  			yyval.pFunc->fileName = els_parsedfile;
	 	 		yyval.pFunc->lineDefined = yypvt[-3].vInt;
	  			memcpy(yyval.pFunc->code, basepc, pc*sizeof(Byte));
	  			funcCode = basepc; maxcode=maxcurr;
				change2main();  
			} 
				break;
			case 14:{ 
				codeIf(yypvt[-4].vLong, yypvt[-2].vLong);
			} 
				break;
			case 15:{
				yyval.vLong=pc;
			} 
				break;
			case 16:{
        		basepc[yypvt[-3].vLong] = IFFJMP;
				code_word_at(basepc+yypvt[-3].vLong+1, pc - (yypvt[-3].vLong + sizeof(Word)+1));
        		basepc[yypvt[-1].vLong] = UPJMP;
				code_word_at(basepc+yypvt[-1].vLong+1, pc - (yypvt[-6].vLong));
       		} 
				break;
			case 17:{
				yyval.vLong=pc;
			} 
				break;
			case 18:{
        		basepc[yypvt[-0].vLong] = IFFUPJMP;
				code_word_at(basepc+yypvt[-0].vLong+1, pc - (yypvt[-4].vLong));
       		}
				break;
			case 19:{
           		int i;
         		compare_mult_assign(nvarbuffer, yypvt[-0].vLong, yypvt[-2].vInt * 2 + nvarbuffer);
	 			for (i=nvarbuffer-1; i>=0; i--) els_codestore (i);
	 			if (yypvt[-2].vInt > 1 || (yypvt[-2].vInt == 1 && varbuffer[0] != 0)) els_codecompare (0);
	
    	    }
				break;
			case 21:{ 
				nlocalvar += yypvt[-1].vInt;
	  			compare_mult_assign(yypvt[-1].vInt, yypvt[-0].vInt, 0);
			} 
				break;
			case 24:{ 
				codeIf(yypvt[-3].vLong, yypvt[-1].vLong); 
			} 
				break;
			case 25:{
				yyval.vInt = nlocalvar;
			} 
				break;
			case 26:{
	  			if (nlocalvar != yypvt[-2].vInt){
           			nlocalvar = yypvt[-2].vInt;
	   				els_codecompare (0);
	  			}
         	} 
				break;
			case 28:{
	   			compare_functioncall(yypvt[-1].vLong, MULT_RET);
           		codereturn();
          	} 
				break;
			case 29:{ 
	  			yyval.vLong = pc;
	  			code_byte(0);		
	  			code_word (0);
         	}
				break;
			case 30:{ 
				compare_functioncall(yypvt[-0].vLong, 1); 
			} 
				break;
			case 31:{ 
				yyval.vLong = yypvt[-1].vLong; 
			} 
				break;
			case 32:{ 
				code_byte(EQOP);   
				yyval.vLong = 0; 
			} 
				break;
			case 33:{ 
				code_byte(LTOP);   
				yyval.vLong = 0; 
			} 
				break;
			case 34:{ 
				code_byte(GTOP);   yyval.vLong = 0; 
			} 
				break;
			case 35:{ 
				code_byte(EQOP); code_byte(NOTOP); yyval.vLong = 0; 
			} 
				break;
			case 36:{ 
				code_byte(LEOP);   yyval.vLong = 0; 
			} 
				break;
			case 37:{ 
				code_byte(GEOP);   yyval.vLong = 0; 
			} 
				break;
			case 38:{ code_byte(ADDOP);  yyval.vLong = 0; } break;
			case 39:{ code_byte(SUBOP);  yyval.vLong = 0; } break;
			case 40:{ code_byte(MULTOP); yyval.vLong = 0; } break;
			case 41:{ code_byte(DIVOP);  yyval.vLong = 0; } break;
			case 42:{ code_byte(POWOP);  yyval.vLong = 0; } break;
			case 43:{ code_byte(CONCOP);  yyval.vLong = 0; } break;
			case 44:{ code_byte(MINUSOP); yyval.vLong = 0;} break;
			case 45:{ yyval.vLong = 0; } break;
			case 46:{ yyval.vLong = 0;} break;
			case 47:{ code_number(yypvt[-0].vFloat); yyval.vLong = 0; } break;
			case 48:{
      			code_byte(PUSHSTRING);
      			code_word(yypvt[-0].vWord);
      			yyval.vLong = 0;
     		} 
				break;
			case 49:{code_byte(PUSHNULL); yyval.vLong = 0; } break;
			case 50:{ yyval.vLong = yypvt[-0].vLong; } break;
			case 51:{ code_byte(NOTOP);  yyval.vLong = 0;} break;
			case 52:{code_byte(POP); } break;
			case 53:{ 
      			basepc[yypvt[-2].vLong] = ONFJMP;
      			code_word_at(basepc+yypvt[-2].vLong+1, pc - (yypvt[-2].vLong + sizeof(Word)+1));
      			yyval.vLong = 0;
     		}
				break;
			case 54:{code_byte(POP); } break;
			case 55:{ 
      			basepc[yypvt[-2].vLong] = ONTJMP;
      			code_word_at(basepc+yypvt[-2].vLong+1, pc - (yypvt[-2].vLong + sizeof(Word)+1));
      			yyval.vLong = 0;
     		}
				break;
			case 56:{
      			code_byte(CREATEARRAY);
      			yyval.vLong = pc; code_word(0);
     		}
				break;
			case 57:{
      			code_word_at(basepc+yypvt[-3].vLong, yypvt[-1].vInt);
     		}
				break;
			case 58:{
	  			code_byte(CALLFUNC);
	  			code_byte(yypvt[-1].vInt+yypvt[-0].vInt);
	  			yyval.vLong = pc;
	  			code_byte(0);  /* may be modified by other rules */
			}
				break;
			case 59:{ yyval.vInt = 0; } break;
			case 60:{ 
            	   code_byte(PUSHSELF); 
	       			code_word(els_vm_findconstant(yypvt[-0].pNode));
               		yyval.vInt = 1;
	     	}
				break;
			case 61:{ yyval.vInt = compare_functioncall(yypvt[-1].vLong, 1); } break;
			case 62:{ yyval.vInt = 1; } break;
			case 63:{ yyval.vLong = 0; } break;
			case 64:{ yyval.vLong = yypvt[-0].vLong; } break;
			case 65:{ if (yypvt[-0].vLong != 0) yyval.vLong = yypvt[-0].vLong; else yyval.vLong = -1; } break;
			case 66:{ yyval.vLong = compare_functioncall(yypvt[-1].vLong, 1); } break;
			case 67:{
	  			if (yypvt[-0].vLong == 0) yyval.vLong = -(yypvt[-1].vLong + 1);  
	  			else{
	    			compare_functioncall(yypvt[-0].vLong, yypvt[-1].vLong);
	    			yyval.vLong = yypvt[-0].vLong;
	  			}
			} 
				break;
			case 68:{ els_codecompare(0); yyval.vInt = els_linenumber; } break;
			case 69:{ els_codecompare(0); yyval.vInt = els_linenumber; } break;
			case 70:{ add_localvar(els_vm_findsymbol(yypvt[-0].pNode));} break;
			case 71:{ add_localvar(els_vm_findsymbol(yypvt[-0].pNode));} break;
			case 72:{ flush_list(yypvt[-0].vInt/FIELDS_PER_FLUSH, yypvt[-0].vInt%FIELDS_PER_FLUSH); } break;
			case 73:{ yyval.vInt = yypvt[-2].vInt+yypvt[-0].vInt; } break;
			case 74:{ yyval.vInt = yypvt[-1].vInt; flush_record(yypvt[-1].vInt%FIELDS_PER_FLUSH); } break;
			case 75:{ yyval.vInt = 0; } break;
			case 76:{ yyval.vInt = yypvt[-0].vInt; flush_record(yypvt[-0].vInt%FIELDS_PER_FLUSH); } break;
			case 79:{ yyval.vInt = 0; } break;
			case 80:{ yyval.vInt = yypvt[-1].vInt; } break;
			case 81:{yyval.vInt=1;} break;
			case 82:{
		  		yyval.vInt=yypvt[-2].vInt+1;
		  		if (yyval.vInt%FIELDS_PER_FLUSH == 0) flush_record(FIELDS_PER_FLUSH);
			}
				break;
			case 83:{ push_field(els_vm_findconstant(yypvt[-2].pNode));} break;
			case 84:{ yyval.vInt = 0; } break;
			case 85:{ yyval.vInt = yypvt[-1].vInt; } break;
			case 86:{yyval.vInt=1;} break;
			case 87:{
		  		yyval.vInt=yypvt[-2].vInt+1;
		  		if (yyval.vInt%FIELDS_PER_FLUSH == 0) 
		    	flush_list(yyval.vInt/FIELDS_PER_FLUSH - 1, FIELDS_PER_FLUSH);
			}
				break;
			case 88:{
	   			nvarbuffer = 0; 
	   			add_varbuffer(yypvt[-0].vLong);
	   			yyval.vInt = (yypvt[-0].vLong == 0) ? 1 : 0;
	  		} 
				break;
			case 89:{ 
	   			add_varbuffer(yypvt[-0].vLong);
	    		yyval.vInt = (yypvt[-0].vLong == 0) ? yypvt[-2].vInt + 1 : yypvt[-2].vInt;
	  		} 
				break;
			case 90:{ yyval.vLong = yypvt[-0].vLong; } break;	
			case 91:{ yyval.vLong = 0; } break;
			case 92:{
	   			code_byte(PUSHSTRING);
	   			code_word(els_vm_findconstant(yypvt[-0].pNode));
	   			yyval.vLong = 0;		
	  		}
				break;
			case 93:{
	   			Word s = els_vm_findsymbol(yypvt[-0].pNode);
	   			int local = els_localname (s);
	   			if (local == -1)	yyval.vLong = s + 1;	
           		else yyval.vLong = -(local+1);	
	  		}
				break;
			case 94:{ els_pushvar(yypvt[-0].vLong); } break;
			case 95:{store_localvar(els_vm_findsymbol(yypvt[-0].pNode), 0); yyval.vInt = 1;} break;
			case 96:{
	     		store_localvar(els_vm_findsymbol(yypvt[-0].pNode), yypvt[-2].vInt);
	     		yyval.vInt = yypvt[-2].vInt+1;
	    	}
				break;
			case 97:{ yyval.vInt = 0; } break;
			case 98:{ yyval.vInt = yypvt[-0].vLong; } break;
			case 99:{ els_debug = yypvt[-0].vInt; } break;
		}
	goto yystack;		
}
